package com.tianji.promotion.utils;

import com.tianji.common.exceptions.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 分布式锁注解切面类
 * </p>
 *
 * @author taohongrun
 * @since 2025/2/16
 */
@Component
@Aspect
@RequiredArgsConstructor
public class MyLockAspect implements Ordered {
    private final RedissonClient redissonClient;
    private final MyLockFactory myLockFactory;

    @Around("@annotation(myLock)")
    public Object tryLock(ProceedingJoinPoint pjp, MyLock myLock) throws Throwable {
        /*
        // 1.创建锁对象
        RLock lock = redissonClient.getLock(myLock.name());
        */

        //1.利用锁工厂获取锁对象
        //MyLockFactory myLockFactory1 = new MyLockFactory(redissonClient); 也可以通过注入方式获取对象
        RLock lock = myLockFactory.getLock(myLock.type(), myLock.name());

        /*
        // 2.尝试获取锁
        boolean isLock = lock.tryLock(myLock.waitTime(), myLock.leaseTime(), myLock.unit());
        */

        //利用策略模式来对应不同参数的tryLock方法（获取锁）
        boolean isLock = myLock.strategy().tryLock(lock, myLock);

        // 3.判断是否成功
        if (!isLock) {
            // 3.1.失败，快速结束
            throw new BadRequestException("请求太频繁");
        }
        try {
            // 3.2.成功，执行业务
            return pjp.proceed();
        } finally {
            // 4.释放锁
            lock.unlock();
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
